<?php

define('FILE_NOT_FOUND', 0x00);
define('DIR_NOT_FOUND', 0x01);
define('IMAGE_NOT_LOADED', 0x10);
define('IMAGE_NOT_CREATED', 0x11);

class AndreLinoge_imageRoutine {

    protected $inputFile;
    protected $currentImage;
    protected $newImage;
    protected $imageInfo;
    protected $imageType;
    protected $JPG_Quality;
    protected $PNG_Quality;

    public function __construct($_FileName = NULL) {
        if (isset($_FileName))
            $this->LoadImage($_FileName);
        $this->JPG_Quality = 85;
        $this->PNG_Quality = 0;
    }

    public function setJpgQuality($newJpqQuality) {
        $newJpqQuality = (int) $newJpqQuality;
        if ($newJpqQuality >= 0 && $newJpqQuality <= 100)
            $this->JPG_Quality = $newJpqQuality;
    }

    public function setPngQuality($newPngQuality) {
        $newPngQuality = (int) $newPngQuality;
        if ($newPngQuality >= 0 && $newPngQuality <= 100)
            $this->PNG_Quality = $newPngQuality;
    }

    public function LoadImage($_FileName) {
        if (!is_file($_FileName))
            throw new Exception(
                    'File does not exist or not found: ' . $_FileName,
                    FILE_NOT_FOUND
            );

        $this->inputFile = $_FileName;
        $this->imageInfo = getimagesize($this->inputFile);

        switch ($this->imageInfo['mime']) {
            case 'image/pjpeg':
            case 'image/jpeg':
                $this->currentImage = imagecreatefromjpeg($this->inputFile);
                $this->imageType = 'JPG';
                return TRUE;
                break;
            case 'image/gif':
                $this->currentImage = imagecreatefromgif($this->inputFile);
                $this->imageType = 'GIF';
                return TRUE;
                break;
            case 'image/png':
                $this->currentImage = imagecreatefrompng($this->inputFile);
                $this->imageType = 'PNG';
                return TRUE;
                break;
            default:
                return FALSE;
                break;
        }
    }

    // Makes a plain copy of the original
    public function Duplicate() {
        if (!isset($this->currentImage) || is_bool($this->currentImage))
            throw new Exception(
                    'Image did not load. Can`t duplicate.',
                    IMAGE_NOT_LOADED
            );

        $this->newImage = $this->currentImage;
        return TRUE;
    }

    // Scale image
    public function Scale($maxWidth, $maxHeight) {
        if (!isset($this->currentImage))
            throw new Exception(
                    'Image did not load. Can`t scale. ',
                    IMAGE_NOT_LOADED
            );

        $prop_form = $maxWidth / $maxHeight;

        $isScaled = FALSE;

        $outputImageType = "";

        $img_width = 0;
        $img_height = 0;

        $width = ImageSX($this->currentImage);
        $height = ImageSY($this->currentImage);
        $prop = $width / $height;

        $isEdited = false;

        $img_width = $width;
        $img_height = $height;

        if ($prop >= $prop_form) {
            if ($width > $maxWidth) {
                $k = $width / $maxWidth;
                $new_width = $maxWidth;
                $new_height = floor($height / $k);
                $isEdited = TRUE;

                $img_width = $new_width;
                $img_height = $new_height;
            }
        } else {
            if ($height > $maxHeight) {
                $k = $height / $maxHeight;
                $new_height = $maxHeight;
                $new_width = floor($width / $k);
                $isEdited = TRUE;

                $img_width = $new_width;
                $img_height = $new_height;
            }
        }

        if ($isEdited) {
            $this->newImage = imagecreatetruecolor($new_width, $new_height);
            imagecopyresampled($this->newImage,
                    $this->currentImage,
                    0, 0, 0, 0,
                    $new_width,
                    $new_height,
                    $width,
                    $height);
            $isScaled = TRUE;
        }

        return ($isScaled ? array(
            'newWidth' => $img_width,
            'newHeight' => $img_height
                ) : FALSE);
    }

    // Makes a resized copy of the original
    public function Resize($_NewWidth, $_NewHeight) {
        if (!isset($this->currentImage))
            throw new Exception(
                    'Image did not load. Can`t resize',
                    IMAGE_NOT_LOADED
            );

        list($width_orig, $height_orig) = getimagesize($this->inputFile);

        $ratio_orig = $width_orig / $height_orig;

        if ($_NewWidth / $_NewHeight > $ratio_orig) {
            $new_height = $_NewWidth / $ratio_orig;
            $new_width = $_NewWidth;
        } else {
            $new_width = $_NewHeight * $ratio_orig;
            $new_height = $_NewHeight;
        }

        $x_mid = $new_width / 2;  //horizontal middle
        $y_mid = $new_height / 2; //vertical middle

        $tmpImage = imagecreatetruecolor(round($new_width), round($new_height));

        imagecopyresampled($tmpImage,
                $this->currentImage,
                0, 0, 0, 0,
                $new_width,
                $new_height,
                $width_orig,
                $height_orig
        );

        $this->newImage = imagecreatetruecolor($_NewWidth, $_NewHeight);

        imagecopyresampled($this->newImage,
                $tmpImage,
                0, 0,
                ($x_mid - ($_NewWidth / 2)),
                ($y_mid - ($_NewHeight / 2)),
                $_NewWidth,
                $_NewHeight,
                $_NewWidth,
                $_NewHeight
        );

        return TRUE;
    }

    // Save copy to file. If no file name omitted it will overwrite the original
    public function SaveImage($newFileName = NULL, $newImageType = NULL, $prefixFileName = NULL) {
        if (!isset($this->newImage))
            throw new Exception(
                    'Nothing to save',
                    IMAGE_NOT_CREATED
            );

        if (!isset($newFileName)) {
            $FileName = $this->inputFile;
        } else {
            $FileName = $newFileName;
        }

        $imageType = $this->imageType;
        if (isset($newImageType)) {
            $newImageType = strtoupper($newImageType);
            if ($newImageType == 'JPG' || $newImageType == 'PNG' ||
                    $newImageType == 'GIF')
                $imageType = $newImageType;
        }

        if (isset($prefixFileName)) {
            $paresFileName = pathinfo($FileName);
            $FileName = $paresFileName['dirname'] .
                    '/' .
                    $prefixFileName .
                    $paresFileName['basename'];
        }

        if ($imageType != $this->imageType) {
            $paresFileName = pathinfo($FileName);
            $FileName = $paresFileName['dirname'] .
                    '/' .
                    $paresFileName['filename'] .
                    '.' . strtolower($imageType);
        }

        switch ($imageType) {
            case 'GIF':
                imagegif($this->newImage, $FileName);
                return TRUE;
                break;
            case 'PNG':
                imagepng($this->newImage, $FileName, $this->PNG_Quality);
                return TRUE;
                break;
            case 'JPG':
            default:
                imagejpeg($this->newImage, $FileName, $this->JPG_Quality);
                return TRUE;
                break;
        }
    }

    // Output copy to browser
    public function ShowInBrowser($showType = 'JPG') {
        if (!isset($this->newImage))
            throw new Exception(
                    'Nothing to show',
                    IMAGE_NOT_CREATED
            );

        $showType = strtoupper($showType);
        switch ($showType) {
            case 'GIF':
                imagegif($this->newImage, NULL);
                return TRUE;
                break;
            case 'PNG':
                imagepng($this->newImage, NULL, $this->PNG_Quality);
                return TRUE;
                break;
            case 'JPG':
            default:
                imagejpeg($this->newImage, NULL, $this->JPG_Quality);
                return TRUE;
                break;
        }
    }

    public function ScaleFolder($inputFolder,
                                $outputFolder,
                                $maxWidth = 100,
                                $maxHeight = 100,
                                $namePrefix = NULL,
                                $newType = NULL) {
        if (!is_dir($inputFolder))
            throw new Exception(
                    'Input folder not found.',
                    DIR_NOT_FOUND
            );

        if (!is_dir($outputFolder))
            throw new Exception(
                    'Output folder not found.',
                    DIR_NOT_FOUND
            );

        $workFolder = opendir($inputFolder);

        while (FALSE !== ($imageFile = readdir($workFolder))) {
            $workFileName = $inputFolder . $imageFile;
            if (!is_file($workFileName)) continue;

            
            if ($this->LoadImage($workFileName)) {
                $this->Scale($maxWidth, $maxHeight);
                $saveFileName = $outputFolder . $imageFile;
                $this->SaveImage($saveFileName, $newType, $namePrefix);
            }
        }
    }

    public function __destruct() {
        //imagedestroy($this->Image);
        //imagedestroy($this->Copy);
        $this->inputFile = NULL;
        $this->imageInfo = NULL;
    }

}

